﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using D2DFactory = SharpDX.Direct2D1.Factory;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Bitmap = SharpDX.Direct2D1.Bitmap;
using PixelFormat = SharpDX.Direct2D1.PixelFormat;

namespace Direct2DDemo
{
    public partial class Form1 : DevExpress.XtraEditors.XtraForm
    {
        private WindowRenderTarget renderTarget;
        private D2DFactory factory;
        private Stopwatch stopwatch = new Stopwatch();
        private long frameCount;
        private bool isRunning;
        private Thread renderThread;
        private Bitmap currentBitmap;
        private readonly object bitmapLock = new object();
        private int fps;
        private Size clientSize;
        private Random rnd = new Random();
        private List<PerformanceRecord> records = new List<PerformanceRecord>();
        private IntPtr imageDataPtr = IntPtr.Zero;
        private int currentDataSize = 0;

        public Form1()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
            this.Text = "Direct2D 图像加载性能测试";
            this.ClientSize = new Size(800, 600);
            clientSize = this.ClientSize;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            InitializeDirect2D();
            StartRendering();
        }

        private void InitializeDirect2D()
        {
            factory = new D2DFactory();
            var renderTargetProperties = new RenderTargetProperties()
            {
                PixelFormat = new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied),
            };

            renderTarget = new WindowRenderTarget(
                factory,
                renderTargetProperties,
                new HwndRenderTargetProperties()
                {
                    Hwnd = this.Handle,
                    PixelSize = new Size2(clientSize.Width, clientSize.Height),
                    PresentOptions = PresentOptions.Immediately
                });
        }

        private void StartRendering()
        {
            if (isRunning) return;

            isRunning = true;
            stopwatch.Restart();
            frameCount = 0;

            renderThread = new Thread(RenderLoop)
            {
                Priority = ThreadPriority.Highest,
                IsBackground = true
            };
            renderThread.Start();
        }

        private void StopRendering()
        {
            isRunning = false;
            renderThread?.Join();
            ReleaseImageData();
        }

        private void ReleaseImageData()
        {
            if (imageDataPtr != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(imageDataPtr);
                imageDataPtr = IntPtr.Zero;
                currentDataSize = 0;
            }
        }

        private void RenderLoop()
        {
            while (isRunning)
            {
                GenerateNewImage();
                RenderFrame();

                frameCount++;
                if (stopwatch.ElapsedMilliseconds >= 1000)
                {
                    fps = (int)(frameCount * 1000 / stopwatch.ElapsedMilliseconds);
                    this.BeginInvoke(new Action(() =>
                        this.Text = $"Direct2D 图像加载测试 | FPS: {fps} | 分辨率: {clientSize.Width}x{clientSize.Height}"));
                    frameCount = 0;
                    stopwatch.Restart();
                }

                // 控制帧率，避免CPU占用100%
                Thread.Sleep(1);
            }
        }

        private void GenerateNewImage()
        {
            lock (bitmapLock)
            {
                currentBitmap?.Dispose();
                currentBitmap = null;
            }

            int width = clientSize.Width;
            int height = clientSize.Height;
            int dataSize = width * height * 4; // 每个像素4字节 (BGRA)

            // 确保有足够的内存空间
            if (dataSize > currentDataSize || imageDataPtr == IntPtr.Zero)
            {
                ReleaseImageData();
                imageDataPtr = Marshal.AllocHGlobal(dataSize);
                currentDataSize = dataSize;
            }

            // 生成随机图像数据
            GenerateRandomImageData(width, height, imageDataPtr, dataSize);

            var bitmapProperties = new BitmapProperties(new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied));
            int stride = width * 4;

            lock (bitmapLock)
            {
                currentBitmap = new Bitmap(
                    renderTarget,
                    new Size2(width, height),
                    new DataPointer(imageDataPtr, dataSize),
                    stride,
                    bitmapProperties);
            }
        }

        private unsafe void GenerateRandomImageData(int width, int height, IntPtr dataPtr, int dataSize)
        {
            // 随机渐变背景
            var color1 = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
            var color2 = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));

            // 计算渐变步长
            float rStep = (color2.R - color1.R) / (float)height;
            float gStep = (color2.G - color1.G) / (float)height;
            float bStep = (color2.B - color1.B) / (float)height;

            // 使用指针直接操作内存
            byte* pData = (byte*)dataPtr.ToPointer();

            for (int y = 0; y < height; y++)
            {
                int currentR = (int)(color1.R + rStep * y);
                int currentG = (int)(color1.G + gStep * y);
                int currentB = (int)(color1.B + bStep * y);

                for (int x = 0; x < width; x++)
                {
                    int index = (y * width + x) * 4;

                    // 添加随机噪点
                    int noise = rnd.Next(-10, 10);

                    // BGRA 格式 (Direct2D标准格式)
                    pData[index] = (byte)Math.Max(0, Math.Min(255, currentB + noise));     // B
                    pData[index + 1] = (byte)Math.Max(0, Math.Min(255, currentG + noise)); // G
                    pData[index + 2] = (byte)Math.Max(0, Math.Min(255, currentR + noise)); // R
                    pData[index + 3] = 255; // A (完全不透明)
                }
            }
        }

        private void RenderFrame()
        {
            try
            {
                renderTarget.BeginDraw();
                renderTarget.Clear(new RawColor4(0.1f, 0.1f, 0.1f, 1.0f));

                lock (bitmapLock)
                {
                    if (currentBitmap != null)
                    {
                        renderTarget.DrawBitmap(
                            currentBitmap,
                            new RawRectangleF(0, 0, clientSize.Width, clientSize.Height),
                            1.0f,
                            BitmapInterpolationMode.Linear);
                    }
                }

                // 绘制性能信息
                using (var brush = new SolidColorBrush(renderTarget, new RawColor4(1.0f, 1.0f, 0.8f, 1.0f)))
                using (var textFormat = new SharpDX.DirectWrite.TextFormat(
                    new SharpDX.DirectWrite.Factory(),
                    "Arial",
                    18))
                {
                    string info = $"FPS: {fps}\n分辨率: {clientSize.Width}x{clientSize.Height}\n帧计数: {frameCount}";
                    renderTarget.DrawText(info, textFormat,
                        new RawRectangleF(10, 10, clientSize.Width - 10, clientSize.Height - 10),
                        brush);
                }

                renderTarget.EndDraw();
            }
            catch (SharpDXException ex)
            {
                Debug.WriteLine($"渲染错误: {ex.Message}");
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (renderTarget != null)
            {
                clientSize = this.ClientSize;
                renderTarget.Resize(new Size2(clientSize.Width, clientSize.Height));
            }
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            StopRendering();
            renderTarget?.Dispose();
            factory?.Dispose();
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.ClientSize = new System.Drawing.Size(800, 600);
            this.Name = "MainForm";
            this.ResumeLayout(false);
        }
    }

    public class PerformanceRecord
    {
        public DateTime Timestamp { get; set; }
        public int FPS { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
    }
}
